<!-- 
 ![[打包流程.html]]
![[脚本模版管理.html]]
![[网元拓扑管理.html]]
 -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>软件升级包打包工具</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <script src="https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js"></script>

  <!-- Tailwind 配置 -->
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            primary: '#165DFF',
            success: '#52C41A',
            warning: '#FAAD14',
            danger: '#FF4D4F',
            'gray-light': '#F2F3F5',
            'gray-medium': '#C9CDD4',
            'gray-dark': '#86909C'
          }
        }
      }
    }
  </script>

  <style type="text/tailwindcss">
    @layer utilities {
      .step-active {
        @apply bg-primary text-white border-primary;
      }
      .step-done {
        @apply bg-success text-white border-success;
      }
      .step-pending {
        @apply bg-white text-gray-dark border-gray-medium;
      }
      .canvas-node {
        @apply rounded-lg p-3 border-2 transition-all duration-300;
      }
      .canvas-node-active {
        @apply border-primary bg-primary/5 scale-105 shadow-md;
      }
      .canvas-line {
        @apply h-1 bg-gray-medium relative;
      }
      .canvas-line-active {
        @apply bg-primary;
      }
      .scale-in {
        animation: scaleIn 0.3s ease-out forwards;
      }
      @keyframes scaleIn {
        from { transform: scale(0.95); opacity: 0; }
        to { transform: scale(1); opacity: 1; }
      }
      .script-required {
        @apply text-xs px-1.5 py-0.5 rounded bg-primary/10 text-primary;
      }
      .script-missing {
        @apply text-xs px-1.5 py-0.5 rounded bg-danger/10 text-danger;
      }
    }
  </style>
</head>

<body class="bg-gray-50 min-h-screen flex flex-col">
  <!-- 顶部导航 -->
  <header class="bg-white shadow-sm border-b border-gray-200">
    <div class="container mx-auto px-4 py-3 flex items-center justify-between">
      <div class="flex items-center space-x-3">
        <i class="fa fa-archive text-primary text-2xl"></i>
        <h1 class="text-xl font-semibold">软件升级包打包工具</h1>
      </div>
      <button class="flex items-center space-x-1 text-gray-600 hover:text-primary transition-colors">
        <i class="fa fa-arrow-left"></i>
        <span>返回拓扑管理</span>
      </button>
    </div>
  </header>

  <!-- 主内容区 -->
  <main class="flex-1 container mx-auto px-4 py-6">
    <div class="flex flex-col lg:flex-row gap-6">
      <!-- 左侧：操作区域 -->
      <div class="w-full lg:w-2/3">
        <!-- 步骤导航 -->
        <div class="mb-6">
          <div class="flex flex-wrap items-center justify-between">
            <!-- 步骤1：包信息 -->
            <div class="flex flex-col items-center mb-4 w-1/4">
              <div id="step1Icon" class="w-10 h-10 rounded-full border-2 step-active flex items-center justify-center mb-2">
                <span>1</span>
              </div>
              <p class="text-sm font-medium">包信息配置</p>
            </div>
            <!-- 连接线1 -->
            <div class="w-1/4 h-1 bg-gray-medium relative -top-6">
              <div id="line1" class="h-full bg-primary w-0 transition-all duration-500"></div>
            </div>
            <!-- 步骤2：拓扑选择 -->
            <div class="flex flex-col items-center mb-4 w-1/4">
              <div id="step2Icon" class="w-10 h-10 rounded-full border-2 step-pending flex items-center justify-center mb-2">
                <span>2</span>
              </div>
              <p class="text-sm font-medium">选择拓扑</p>
            </div>
            <!-- 连接线2 -->
            <div class="w-1/4 h-1 bg-gray-medium relative -top-6">
              <div id="line2" class="h-full bg-primary w-0 transition-all duration-500"></div>
            </div>
            <!-- 步骤3：文件上传 -->
            <div class="flex flex-col items-center mb-4 w-1/4">
              <div id="step3Icon" class="w-10 h-10 rounded-full border-2 step-pending flex items-center justify-center mb-2">
                <span>3</span>
              </div>
              <p class="text-sm font-medium">文件上传</p>
            </div>
            <!-- 连接线3 -->
            <div class="w-1/4 h-1 bg-gray-medium relative -top-6">
              <div id="line3" class="h-full bg-primary w-0 transition-all duration-500"></div>
            </div>
            <!-- 步骤4：打包生成 -->
            <div class="flex flex-col items-center w-1/4">
              <div id="step4Icon" class="w-10 h-10 rounded-full border-2 step-pending flex items-center justify-center mb-2">
                <span>4</span>
              </div>
              <p class="text-sm font-medium">打包生成</p>
            </div>
          </div>
        </div>

        <!-- 步骤内容容器 -->
        <div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
          <!-- 步骤1：包信息配置 -->
          <div id="step1Content" class="p-6 scale-in">
            <h2 class="text-lg font-semibold mb-4">升级包基本信息</h2>
            <form id="packageForm" class="space-y-4">
              <div>
                <label for="packageName" class="block text-sm font-medium text-gray-700 mb-1">升级包名称 <span class="text-danger">*</span></label>
                <input type="text" id="packageName" placeholder="例如：NCP2-Upgrade" 
                       class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary">
              </div>
              
              <div>
                <label for="versionDesc" class="block text-sm font-medium text-gray-700 mb-1">版本描述文件 <span class="text-danger">*</span></label>
                <div id="descFileUpload" class="border-2 border-dashed border-gray-medium rounded-lg p-6 text-center hover:border-primary transition-colors cursor-pointer">
                  <input type="file" id="versionDescFile" class="hidden" accept=".txt,.md">
                  <i class="fa fa-file-text-o text-3xl text-gray-medium mb-2"></i>
                  <p class="text-sm text-gray-dark mb-1">点击或拖拽文件至此处上传</p>
                  <p class="text-xs text-gray-500">支持 .txt / .md 格式，最大 10MB</p>
                  <div id="descFilePreview" class="mt-3 hidden">
                    <div class="flex items-center justify-between bg-gray-light p-2 rounded">
                      <div class="flex items-center space-x-2">
                        <i class="fa fa-file-text text-primary"></i>
                        <span id="descFileName" class="text-sm truncate max-w-xs"></span>
                      </div>
                      <button type="button" id="removeDescFile" class="text-danger hover:text-danger/80">
                        <i class="fa fa-times"></i>
                      </button>
                    </div>
                  </div>
                </div>
              </div>
            </form>
            <div class="mt-6 flex justify-end">
              <button id="toStep2Btn" class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-lg flex items-center space-x-2 transition-all">
                <span>下一步：选择拓扑</span>
                <i class="fa fa-arrow-right"></i>
              </button>
            </div>
          </div>

          <!-- 步骤2：选择拓扑 -->
          <div id="step2Content" class="p-6 hidden">
            <div class="flex justify-between items-center mb-4">
              <h2 class="text-lg font-semibold">选择待打包拓扑</h2>
              <div class="relative">
                <input type="text" id="topologySearch" placeholder="搜索网元..." 
                       class="pl-8 pr-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary w-48">
                <i class="fa fa-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm"></i>
              </div>
            </div>
            
            <!-- 单拓扑选择提示 -->
            <div class="bg-primary/5 border border-primary/20 rounded-lg p-3 mb-4">
              <p class="text-sm text-primary flex items-center">
                <i class="fa fa-info-circle mr-2"></i> 每次打包只能选择一个网元拓扑
              </p>
            </div>

            <!-- 拓扑列表 -->
            <div class="max-h-[400px] overflow-y-auto pr-2 space-y-2 mb-6">
              <!-- 拓扑1 -->
              <div class="border border-gray-200 rounded-lg p-3 hover:border-primary transition-colors cursor-pointer topology-item" data-neid="NCP2" data-nename="核心网元2">
                <div class="flex items-center justify-between">
                  <div class="flex items-center space-x-2">
                    <input type="radio" name="topology" class="topology-radio" id="topo1">
                    <label for="topo1" class="font-medium cursor-pointer">网元拓扑 [NCP2] - 核心网元2</label>
                  </div>
                  <button class="text-primary text-sm hover:text-primary/80 view-modules-btn" data-target="modules1">
                    查看模块 <i class="fa fa-chevron-down text-xs"></i>
                  </button>
                </div>
                <!-- 模块列表 -->
                <div id="modules1" class="ml-6 mt-2 border-l-2 border-gray-light pl-3 hidden">
                  <div class="mb-1 text-sm">
                    <span class="text-gray-dark">模块1：</span>
                    <span>订单服务（升级顺序：00001）</span>
                  </div>
                  <div class="text-sm">
                    <span class="text-gray-dark">模块2：</span>
                    <span>支付服务（升级顺序：00002）</span>
                  </div>
                </div>
              </div>

              <!-- 拓扑2 -->
              <div class="border border-gray-200 rounded-lg p-3 hover:border-primary transition-colors cursor-pointer topology-item" data-neid="NCP3" data-nename="核心网元3">
                <div class="flex items-center justify-between">
                  <div class="flex items-center space-x-2">
                    <input type="radio" name="topology" class="topology-radio" id="topo2">
                    <label for="topo2" class="font-medium cursor-pointer">网元拓扑 [NCP3] - 核心网元3</label>
                  </div>
                  <button class="text-primary text-sm hover:text-primary/80 view-modules-btn" data-target="modules2">
                    查看模块 <i class="fa fa-chevron-down text-xs"></i>
                  </button>
                </div>
                <!-- 模块列表 -->
                <div id="modules2" class="ml-6 mt-2 border-l-2 border-gray-light pl-3 hidden">
                  <div class="text-sm">
                    <span class="text-gray-dark">模块1：</span>
                    <span>用户服务（升级顺序：00001）</span>
                  </div>
                </div>
              </div>

              <!-- 拓扑3（无模块） -->
              <div class="border border-gray-200 rounded-lg p-3 hover:border-primary transition-colors cursor-pointer topology-item" data-neid="NCP4" data-nename="核心网元4">
                <div class="flex items-center justify-between">
                  <div class="flex items-center space-x-2">
                    <input type="radio" name="topology" class="topology-radio" id="topo3" disabled>
                    <label for="topo3" class="font-medium text-gray-500 cursor-not-allowed">网元拓扑 [NCP4] - 核心网元4（无模块）</label>
                  </div>
                  <span class="text-gray-500 text-sm">无模块</span>
                </div>
              </div>
            </div>

            <!-- 已选拓扑预览 -->
            <div class="bg-gray-light rounded-lg p-4 mb-6">
              <h3 class="text-sm font-medium mb-2">已选择拓扑</h3>
              <div id="selectedTopos" class="flex flex-wrap gap-2">
                <p class="text-gray-dark text-sm italic">未选择任何拓扑</p>
              </div>
            </div>

            <div class="flex justify-between">
              <button id="backToStep1Btn" class="border border-gray-300 hover:bg-gray-50 text-gray-700 px-4 py-2 rounded-lg flex items-center space-x-2 transition-all">
                <i class="fa fa-arrow-left"></i>
                <span>上一步</span>
              </button>
              <button id="toStep3Btn" class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-lg flex items-center space-x-2 transition-all" disabled>
                <span>下一步：上传文件</span>
                <i class="fa fa-arrow-right"></i>
              </button>
            </div>
          </div>

          <!-- 步骤3：文件上传 -->
          <div id="step3Content" class="p-6 hidden">
            <h2 class="text-lg font-semibold mb-4">按模块上传升级文件</h2>
            <p class="text-sm text-gray-dark mb-6">提示：请为每个模块上传所需的升级文件（包括软件包和配套脚本）</p>
            
            <!-- 脚本要求提示 -->
            <div class="bg-warning/10 border border-warning/30 rounded-lg p-3 mb-6">
              <p class="text-sm text-warning flex items-center">
                <i class="fa fa-exclamation-circle mr-2"></i> 脚本文件必须包含以下所有内容（不能重复也不能缺少）
              </p>
              <div class="mt-2 flex flex-wrap gap-1">
                <span class="script-required">代码检查</span>
                <span class="script-required">完整性校验</span>
                <span class="script-required">环境安全检查</span>
                <span class="script-required">配置文件网关检查</span>
                <span class="script-required">备份</span>
                <span class="script-required">参数配置</span>
                <span class="script-required">释放用户</span>
                <span class="script-required">装载</span>
                <span class="script-required">接入用户</span>
                <span class="script-required">删除软件包</span>
              </div>
            </div>

            <!-- 已选拓扑的模块文件上传列表 -->
            <div id="moduleFileUploads" class="space-y-6 mb-6">
              <!-- 拓扑1：NCP2（默认显示，实际会根据选择动态生成） -->
              <div class="border border-gray-200 rounded-lg overflow-hidden">
                <div class="bg-gray-light px-4 py-2 font-medium">网元拓扑 [NCP2] - 核心网元2</div>
                <div class="p-4 space-y-4">
                  <!-- 模块1：订单服务 -->
                  <div class="module-upload-item" data-module="订单服务" data-order="00001">
                    <div class="flex justify-between items-center mb-2">
                      <div class="flex items-center space-x-2">
                        <i class="fa fa-cube text-warning"></i>
                        <h3 class="font-medium">模块：订单服务 <span class="text-sm text-gray-dark">(升级顺序：00001)</span></h3>
                      </div>
                      <span class="text-xs px-2 py-1 bg-gray-light rounded-full file-status">待上传</span>
                    </div>
                    
                    <!-- 脚本包选择 -->
                    <div class="mb-4">
                      <label class="block text-sm font-medium text-gray-700 mb-1">模块脚本包 <span class="text-danger">*</span></label>
                      <div class="flex gap-2">
                        <select class="module-script-select flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary">
                          <option value="">-- 选择已上传的脚本包 --</option>
                          <option value="script-package-1.0.0.zip">基础脚本包 v1.0.0</option>
                          <option value="script-package-1.1.0.zip">增强脚本包 v1.1.0</option>
                          <option value="custom">-- 手动上传自定义脚本包 --</option>
                        </select>
                        <button type="button" class="text-primary hover:text-primary/80" onclick="openScriptManager()">
                          <i class="fa fa-cog"></i>
                        </button>
                      </div>
                      <div class="custom-script-upload hidden mt-2">
                        <div class="border-2 border-dashed border-gray-medium rounded-lg p-3 text-center hover:border-primary transition-colors cursor-pointer">
                          <input type="file" class="custom-script-file hidden" accept=".zip,.tar,.gz,.sh,.py,.bat">
                          <i class="fa fa-file-code-o text-xl text-gray-medium mb-1"></i>
                          <p class="text-sm text-gray-dark">点击或拖拽脚本文件至此处上传</p>
                          <p class="text-xs text-gray-500">支持 .zip / .tar / .gz / .sh / .py / .bat 格式</p>
                          <div class="script-preview mt-2 hidden"></div>
                        </div>
                      </div>
                      <!-- 脚本检查结果 -->
                      <div class="script-check-result mt-2 text-xs hidden">
                        <p class="font-medium">脚本检查结果：</p>
                        <div class="mt-1 flex flex-wrap gap-1" id="scriptCheckResult1"></div>
                      </div>
                    </div>
                    
                    <!-- 其他升级文件上传区 -->
                    <div>
                      <label class="block text-sm font-medium text-gray-700 mb-1">其他升级文件（软件包等） <span class="text-danger">*</span></label>
                      <div class="file-upload-area border-2 border-dashed border-gray-medium rounded-lg p-4 text-center hover:border-primary transition-colors cursor-pointer">
                        <input type="file" class="module-file-upload hidden" multiple accept=".zip,.tar,.gz,.jar">
                        <i class="fa fa-files-o text-2xl text-gray-medium mb-1"></i>
                        <p class="text-sm text-gray-dark">点击或拖拽文件至此处上传（可多选）</p>
                        <p class="text-xs text-gray-500">支持 .zip / .tar / .gz / .jar 格式</p>
                        <div class="file-preview mt-2 hidden"></div>
                      </div>
                    </div>
                  </div>
                  
                  <!-- 模块2：支付服务 -->
                  <div class="module-upload-item" data-module="支付服务" data-order="00002">
                    <div class="flex justify-between items-center mb-2">
                      <div class="flex items-center space-x-2">
                        <i class="fa fa-cube text-warning"></i>
                        <h3 class="font-medium">模块：支付服务 <span class="text-sm text-gray-dark">(升级顺序：00002)</span></h3>
                      </div>
                      <span class="text-xs px-2 py-1 bg-gray-light rounded-full file-status">待上传</span>
                    </div>
                    
                    <!-- 脚本包选择 -->
                    <div class="mb-4">
                      <label class="block text-sm font-medium text-gray-700 mb-1">模块脚本包 <span class="text-danger">*</span></label>
                      <div class="flex gap-2">
                        <select class="module-script-select flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary">
                          <option value="">-- 选择已上传的脚本包 --</option>
                          <option value="script-package-1.0.0.zip">基础脚本包 v1.0.0</option>
                          <option value="script-package-1.1.0.zip">增强脚本包 v1.1.0</option>
                          <option value="custom">-- 手动上传自定义脚本包 --</option>
                        </select>
                        <button type="button" class="text-primary hover:text-primary/80" onclick="openScriptManager()">
                          <i class="fa fa-cog"></i>
                        </button>
                      </div>
                      <div class="custom-script-upload hidden mt-2">
                        <div class="border-2 border-dashed border-gray-medium rounded-lg p-3 text-center hover:border-primary transition-colors cursor-pointer">
                          <input type="file" class="custom-script-file hidden" accept=".zip,.tar,.gz,.sh,.py,.bat">
                          <i class="fa fa-file-code-o text-xl text-gray-medium mb-1"></i>
                          <p class="text-sm text-gray-dark">点击或拖拽脚本文件至此处上传</p>
                          <p class="text-xs text-gray-500">支持 .zip / .tar / .gz / .sh / .py / .bat 格式</p>
                          <div class="script-preview mt-2 hidden"></div>
                        </div>
                      </div>
                      <!-- 脚本检查结果 -->
                      <div class="script-check-result mt-2 text-xs hidden">
                        <p class="font-medium">脚本检查结果：</p>
                        <div class="mt-1 flex flex-wrap gap-1" id="scriptCheckResult2"></div>
                      </div>
                    </div>
                    
                    <!-- 其他升级文件上传区 -->
                    <div>
                      <label class="block text-sm font-medium text-gray-700 mb-1">其他升级文件（软件包等） <span class="text-danger">*</span></label>
                      <div class="file-upload-area border-2 border-dashed border-gray-medium rounded-lg p-4 text-center hover:border-primary transition-colors cursor-pointer">
                        <input type="file" class="module-file-upload hidden" multiple accept=".zip,.tar,.gz,.jar">
                        <i class="fa fa-files-o text-2xl text-gray-medium mb-1"></i>
                        <p class="text-sm text-gray-dark">点击或拖拽文件至此处上传（可多选）</p>
                        <p class="text-xs text-gray-500">支持 .zip / .tar / .gz / .jar 格式</p>
                        <div class="file-preview mt-2 hidden"></div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <div class="flex justify-between">
              <button id="backToStep2Btn" class="border border-gray-300 hover:bg-gray-50 text-gray-700 px-4 py-2 rounded-lg flex items-center space-x-2 transition-all">
                <i class="fa fa-arrow-left"></i>
                <span>上一步</span>
              </button>
              <button id="toStep4Btn" class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-lg flex items-center space-x-2 transition-all" disabled>
                <span>下一步：打包生成</span>
                <i class="fa fa-arrow-right"></i>
              </button>
            </div>
          </div>

          <!-- 步骤4：打包生成 -->
          <div id="step4Content" class="p-6 hidden">
            <h2 class="text-lg font-semibold mb-4">打包配置确认</h2>
            
            <!-- 脚本完整性检查结果 -->
            <div id="scriptIntegrityCheck" class="mb-6 p-3 rounded-lg border">
              <div class="flex items-center">
                <i class="fa fa-check-circle text-success mr-2"></i>
                <h3 class="font-medium">脚本完整性检查通过</h3>
              </div>
              <p class="text-sm text-gray-dark mt-1">所有必需的脚本文件均已包含且无重复</p>
            </div>
            
            <!-- 打包信息摘要 -->
            <div class="border border-gray-200 rounded-lg mb-6">
              <div class="bg-gray-light px-4 py-2 font-medium">升级包信息</div>
              <div class="p-4 space-y-2 text-sm">
                <div class="grid grid-cols-3 gap-2">
                  <span class="text-gray-dark">包名称：</span>
                  <span class="col-span-2 font-medium" id="summaryPackageName">-</span>
                </div>
                <div class="grid grid-cols-3 gap-2">
                  <span class="text-gray-dark">版本描述：</span>
                  <span class="col-span-2" id="summaryDescFile">-</span>
                </div>
                <div class="grid grid-cols-3 gap-2">
                  <span class="text-gray-dark">包含拓扑：</span>
                  <span class="col-span-2" id="summaryTopologies">-</span>
                </div>
                <div class="grid grid-cols-3 gap-2">
                  <span class="text-gray-dark">总模块数：</span>
                  <span class="col-span-2" id="summaryModuleCount">-</span>
                </div>
                <div class="grid grid-cols-3 gap-2">
                  <span class="text-gray-dark">打包格式：</span>
                  <span class="col-span-2" id="summaryPackageFormat">-</span>
                </div>
              </div>
            </div>
            
            <!-- 打包选项 -->
            <div class="border border-gray-200 rounded-lg mb-6">
              <div class="bg-gray-light px-4 py-2 font-medium">打包选项</div>
              <div class="p-4 space-y-3">
                <div class="flex items-center">
                  <input type="checkbox" id="includeChecksum" checked class="mr-2" disabled>
                  <label for="includeChecksum" class="text-sm">生成文件校验和（MD5） <span class="text-gray-dark text-xs">(必填)</span></label>
                </div>
                <div>
                  <label for="packageFormat" class="block text-sm font-medium text-gray-700 mb-1">打包格式</label>
                  <select id="packageFormat" class="px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary">
                    <option value="zip">ZIP 格式（推荐）</option>
                    <option value="tar.gz">TAR.GZ 格式</option>
                  </select>
                </div>
              </div>
            </div>
            
            <!-- 打包进度 -->
            <div id="packagingProgress" class="mb-6 hidden">
              <div class="flex justify-between items-center mb-2">
                <h3 class="text-sm font-medium">正在打包...</h3>
                <span id="progressPercent" class="text-sm text-primary">0%</span>
              </div>
              <div class="h-2 bg-gray-light rounded-full overflow-hidden">
                <div id="progressBar" class="h-full bg-primary w-0 transition-all duration-300"></div>
              </div>
              <p id="progressMessage" class="text-xs text-gray-dark mt-1">准备打包文件...</p>
            </div>
            
            <!-- 打包完成 -->
            <div id="packagingComplete" class="mb-6 hidden">
              <div class="bg-success/10 border border-success/30 rounded-lg p-4">
                <div class="flex items-start">
                  <i class="fa fa-check-circle text-success text-xl mt-0.5 mr-3"></i>
                  <div>
                    <h3 class="font-medium text-success">打包完成！</h3>
                    <p class="text-sm text-gray-700 mt-1">升级包已成功生成，包含MD5校验信息，可下载后发送给运维人员进行升级操作。</p>
                    <div class="mt-3 flex items-center">
                      <i class="fa fa-file-archive-o text-gray-500 mr-2"></i>
                      <span id="finalPackageName" class="text-sm mr-3">NCP2-Upgrade.zip</span>
                      <button id="downloadPackageBtn" class="text-primary hover:text-primary/80 text-sm flex items-center">
                        <i class="fa fa-download mr-1"></i> 下载
                      </button>
                    </div>
                    <div class="mt-3 p-2 bg-gray-light rounded text-xs">
                      <p class="text-gray-dark">MD5校验值：<span id="packageMd5" class="font-mono">d41d8cd98f00b204e9800998ecf8427e</span></p>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <div class="flex justify-between">
              <button id="backToStep3Btn" class="border border-gray-300 hover:bg-gray-50 text-gray-700 px-4 py-2 rounded-lg flex items-center space-x-2 transition-all">
                <i class="fa fa-arrow-left"></i>
                <span>上一步</span>
              </button>
              <button id="startPackagingBtn" class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-lg flex items-center space-x-2 transition-all">
                <i class="fa fa-cog mr-1"></i>
                <span>开始打包</span>
              </button>
            </div>
          </div>
        </div>
      </div>

      <!-- 右侧：流程画布 -->
      <div class="w-full lg:w-1/3">
        <div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden sticky top-4">
          <div class="p-4 border-b border-gray-200 bg-gray-50">
            <h2 class="font-medium">打包流程</h2>
          </div>
          
          <div class="p-6">
            <div class="flex flex-col items-center">
              <!-- 步骤1：包信息节点 -->
              <div id="canvasStep1" class="canvas-node canvas-node-active w-full border border-primary bg-primary/5 mb-2">
                <div class="flex items-center">
                  <div class="w-8 h-8 rounded-full bg-primary text-white flex items-center justify-center flex-shrink-0">1</div>
                  <div class="ml-3">
                    <h3 class="font-medium text-sm">包信息配置</h3>
                    <p class="text-xs text-gray-dark mt-0.5">设置升级包名称和描述文件</p>
                  </div>
                </div>
              </div>
              
              <!-- 连接线1 -->
              <div class="canvas-line w-1/4 mb-2">
                <div id="canvasLine1" class="h-full w-0 bg-primary transition-all duration-500"></div>
              </div>
              
              <!-- 步骤2：拓扑选择节点 -->
              <div id="canvasStep2" class="canvas-node step-pending w-full mb-2">
                <div class="flex items-center">
                  <div class="w-8 h-8 rounded-full border-2 step-pending flex items-center justify-center flex-shrink-0">2</div>
                  <div class="ml-3">
                    <h3 class="font-medium text-sm">选择拓扑</h3>
                    <p class="text-xs text-gray-dark mt-0.5">选择一个需要打包的网元拓扑</p>
                  </div>
                </div>
              </div>
              
              <!-- 连接线2 -->
              <div class="canvas-line w-1/4 mb-2">
                <div id="canvasLine2" class="h-full w-0 bg-primary transition-all duration-500"></div>
              </div>
              
              <!-- 步骤3：文件上传节点 -->
              <div id="canvasStep3" class="canvas-node step-pending w-full mb-2">
                <div class="flex items-center">
                  <div class="w-8 h-8 rounded-full border-2 step-pending flex items-center justify-center flex-shrink-0">3</div>
                  <div class="ml-3">
                    <h3 class="font-medium text-sm">文件上传</h3>
                    <p class="text-xs text-gray-dark mt-0.5">选择或上传模块脚本和升级文件</p>
                  </div>
                </div>
              </div>
              
              <!-- 连接线3 -->
              <div class="canvas-line w-1/4 mb-2">
                <div id="canvasLine3" class="h-full w-0 bg-primary transition-all duration-500"></div>
              </div>
              
              <!-- 步骤4：打包生成节点 -->
              <div id="canvasStep4" class="canvas-node step-pending w-full">
                <div class="flex items-center">
                  <div class="w-8 h-8 rounded-full border-2 step-pending flex items-center justify-center flex-shrink-0">4</div>
                  <div class="ml-3">
                    <h3 class="font-medium text-sm">打包生成</h3>
                    <p class="text-xs text-gray-dark mt-0.5">生成带MD5校验的升级包</p>
                  </div>
                </div>
              </div>
            </div>
            
            <!-- 当前状态提示 -->
            <div class="mt-8 bg-gray-light rounded-lg p-4">
              <h3 class="text-sm font-medium mb-2">当前状态</h3>
              <div id="currentStatus" class="text-sm">
                <p>请完成升级包基本信息配置，包括名称和描述文件。</p>
              </div>
              <div class="mt-4">
                <button id="helpBtn" class="text-primary hover:text-primary/80 text-sm flex items-center">
                  <i class="fa fa-question-circle mr-1"></i> 查看帮助
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </main>

  <!-- 脚本管理工具模态框 -->
  <div id="scriptManagerModal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 hidden">
    <div class="bg-white rounded-xl shadow-lg w-full max-w-2xl max-h-[80vh] overflow-y-auto scale-in">
      <div class="p-5 border-b border-gray-200 flex justify-between items-center">
        <h3 class="text-lg font-semibold">升级模块脚本管理工具</h3>
        <button class="text-gray-500 hover:text-gray-700" onclick="closeModal('scriptManagerModal')">
          <i class="fa fa-times"></i>
        </button>
      </div>
      
      <div class="p-5">
        <!-- 这里是简化版升级模块脚本管理工具内容 -->
        <div class="mb-4">
          <h4 class="font-medium mb-2">已上传的脚本包</h4>
          <div class="space-y-2">
            <div class="border border-gray-200 rounded-lg p-3 flex justify-between items-center">
              <div>
                <p class="font-medium">基础脚本包 v1.0.0</p>
                <p class="text-xs text-gray-dark">包含所有必需的升级脚本</p>
              </div>
              <button class="text-primary text-sm" onclick="selectScriptPackage('script-package-1.0.0.zip')">选择</button>
            </div>
            <div class="border border-gray-200 rounded-lg p-3 flex justify-between items-center">
              <div>
                <p class="font-medium">增强脚本包 v1.1.0</p>
                <p class="text-xs text-gray-dark">包含所有必需的升级脚本及扩展功能</p>
              </div>
              <button class="text-primary text-sm" onclick="selectScriptPackage('script-package-1.1.0.zip')">选择</button>
            </div>
          </div>
        </div>
        
        <div class="border-t border-gray-200 pt-4">
          <h4 class="font-medium mb-2">上传新脚本包</h4>
          <div class="border-2 border-dashed border-gray-medium rounded-lg p-4 text-center hover:border-primary transition-colors cursor-pointer">
            <input type="file" id="newScriptPackage" class="hidden" accept=".zip,.tar,.gz">
            <i class="fa fa-upload text-2xl text-gray-medium mb-2"></i>
            <p class="text-sm text-gray-dark mb-1">点击或拖拽脚本包至此处上传</p>
            <p class="text-xs text-gray-500">支持 .zip / .tar / .gz 格式的脚本包</p>
          </div>
        </div>
      </div>
      
      <div class="p-4 border-t border-gray-200 flex justify-end">
        <button class="px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors duration-200" onclick="closeModal('scriptManagerModal')">
          关闭
        </button>
      </div>
    </div>
  </div>

  <!-- 帮助模态框 -->
  <div id="helpModal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 hidden">
    <div class="bg-white rounded-xl shadow-lg w-full max-w-md max-h-[80vh] overflow-y-auto scale-in">
      <div class="p-5 border-b border-gray-200 flex justify-between items-center">
        <h3 class="text-lg font-semibold">打包流程帮助</h3>
        <button class="text-gray-500 hover:text-gray-700" onclick="closeModal('helpModal')">
          <i class="fa fa-times"></i>
        </button>
      </div>
      
      <div class="p-5 space-y-4">
        <div>
          <h4 class="font-medium text-primary flex items-center">
            <i class="fa fa-info-circle mr-2"></i> 打包流程说明
          </h4>
          <p class="text-sm text-gray-700 mt-1">该工具帮助您将网元拓扑的模块文件打包为一个升级包，包含必要的MD5校验信息。</p>
        </div>
        
        <div>
          <h4 class="font-medium">步骤1：包信息配置</h4>
          <p class="text-sm text-gray-700 mt-1">设置升级包的基本信息，包括名称和版本描述文件。</p>
        </div>
        
        <div>
          <h4 class="font-medium">步骤2：选择拓扑</h4>
          <p class="text-sm text-gray-700 mt-1">每次打包只能选择一个网元拓扑，系统会显示该拓扑包含的所有模块。</p>
        </div>
        
        <div>
          <h4 class="font-medium">步骤3：文件上传</h4>
          <p class="text-sm text-gray-700 mt-1">为每个模块选择或上传脚本包，并上传其他升级文件（软件包等）。</p>
          <p class="text-sm text-gray-700 mt-1">脚本包必须包含所有必需的脚本文件，系统会自动进行完整性检查。</p>
        </div>
        
        <div>
          <h4 class="font-medium">步骤4：打包生成</h4>
          <p class="text-sm text-gray-700 mt-1">系统会自动生成包含所有文件和MD5校验信息的升级包，您可以下载并使用。</p>
        </div>
      </div>
      
      <div class="p-4 border-t border-gray-200 flex justify-end">
        <button class="px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors duration-200" onclick="closeModal('helpModal')">
          我知道了
        </button>
      </div>
    </div>
  </div>

  <!-- 提示消息 -->
  <div id="toast" class="fixed top-4 right-4 px-4 py-3 rounded-lg shadow-lg transform translate-x-full transition-transform duration-300 flex items-center space-x-2 z-50"></div>

  <script>
    // 必需的脚本列表
    const REQUIRED_SCRIPTS = [
      {code: "CODE_CHECK", name: "代码检查"},
      {code: "INTERGRITY_CHECK", name: "完整性校验"},
      {code: "SECURITY_CHECK", name: "环境安全检查"},
      {code: "CONFIG_CENTER_CHECK", name: "配置文件网关检查"},
      {code: "BACKUP", name: "备份"},
      {code: "CONFIG_CHECK", name: "参数配置"},
      {code: "RELEASE_USER", name: "释放用户"},
      {code: "UPGRADE", name: "装载"},
      {code: "RELOAD_USER", name: "接入用户"},
      {code: "DELETE_PACKAGE", name: "删除软件包"}
    ];
    
    // 当前选中的脚本包
    let currentScriptPackage = null;
    
    // 页面加载完成后初始化
    document.addEventListener('DOMContentLoaded', function() {
      // 初始化步骤导航
      initSteps();
      
      // 初始化文件上传功能
      initFileUploads();
      
      // 初始化拓扑选择功能
      initTopologySelection();
      
      // 初始化脚本选择功能
      initScriptSelection();
      
      // 初始化打包功能
      initPackaging();
    });
    
    // 初始化步骤导航
    function initSteps() {
      // 步骤1 -> 步骤2
      document.getElementById('toStep2Btn').addEventListener('click', function() {
        if (validateStep1()) {
          goToStep(2);
        }
      });
      
      // 步骤2 -> 步骤1
      document.getElementById('backToStep1Btn').addEventListener('click', function() {
        goToStep(1);
      });
      
      // 步骤2 -> 步骤3
      document.getElementById('toStep3Btn').addEventListener('click', function() {
        goToStep(3);
        updateSummaryInfo();
      });
      
      // 步骤3 -> 步骤2
      document.getElementById('backToStep2Btn').addEventListener('click', function() {
        goToStep(2);
      });
      
      // 步骤3 -> 步骤4
      document.getElementById('toStep4Btn').addEventListener('click', function() {
        if (validateScriptIntegrity()) {
          goToStep(4);
          updateSummaryInfo();
        }
      });
      
      // 步骤4 -> 步骤3
      document.getElementById('backToStep3Btn').addEventListener('click', function() {
        goToStep(3);
      });
      
      // 帮助按钮
      document.getElementById('helpBtn').addEventListener('click', function() {
        openModal('helpModal');
      });
    }
    
    // 切换到指定步骤
    function goToStep(step) {
      // 隐藏所有步骤内容
      document.getElementById('step1Content').classList.add('hidden');
      document.getElementById('step2Content').classList.add('hidden');
      document.getElementById('step3Content').classList.add('hidden');
      document.getElementById('step4Content').classList.add('hidden');
      
      // 重置所有步骤样式
      for (let i = 1; i <= 4; i++) {
        document.getElementById(`step${i}Icon`).classList.remove('step-active', 'step-done', 'step-pending');
        document.getElementById(`step${i}Icon`).classList.add('step-pending');
        document.getElementById(`canvasStep${i}`).classList.remove('canvas-node-active', 'step-pending');
        document.getElementById(`canvasStep${i}`).classList.add('step-pending');
        
        const canvasLine = document.getElementById(`canvasLine${i}`);
        if (canvasLine) {
          canvasLine.style.width = '0%';
        }
      }
      
      // 更新已完成步骤
      for (let i = 1; i < step; i++) {
        document.getElementById(`step${i}Icon`).classList.remove('step-active', 'step-pending');
        document.getElementById(`step${i}Icon`).classList.add('step-done');
        
        const canvasLine = document.getElementById(`canvasLine${i}`);
        if (canvasLine) {
          canvasLine.style.width = '100%';
        }
      }
      
      // 更新当前步骤
      document.getElementById(`step${step}Icon`).classList.remove('step-done', 'step-pending');
      document.getElementById(`step${step}Icon`).classList.add('step-active');
      document.getElementById(`canvasStep${step}`).classList.remove('step-pending');
      document.getElementById(`canvasStep${step}`).classList.add('canvas-node-active');
      
      // 显示当前步骤内容
      document.getElementById(`step${step}Content`).classList.remove('hidden');
      document.getElementById(`step${step}Content`).classList.add('scale-in');
      
      // 更新当前状态提示
      updateCurrentStatus(step);
    }
    
    // 更新当前状态提示
    function updateCurrentStatus(step) {
      const statusEl = document.getElementById('currentStatus');
      switch(step) {
        case 1:
          statusEl.innerHTML = '<p>请完成升级包基本信息配置，包括名称和描述文件。</p>';
          break;
        case 2:
          statusEl.innerHTML = '<p>请选择一个需要包含在本次升级包中的网元拓扑。</p>';
          break;
        case 3:
          statusEl.innerHTML = '<p>请为每个模块选择或上传脚本包，并上传其他升级文件。</p>';
          break;
        case 4:
          statusEl.innerHTML = '<p>确认打包信息，点击"开始打包"生成包含MD5校验的升级包。</p>';
          break;
      }
    }
    
    // 验证步骤1
    function validateStep1() {
      const packageName = document.getElementById('packageName').value.trim();
      const descFile = document.getElementById('versionDescFile').files.length > 0;
      
      // 清除之前的错误状态
      document.getElementById('packageName').classList.remove('border-danger');
      document.getElementById('descFileUpload').classList.remove('border-danger');
      
      if (!packageName) {
        document.getElementById('packageName').classList.add('border-danger');
        showToast('请输入升级包名称', 'error');
        return false;
      }
      
      if (!descFile) {
        document.getElementById('descFileUpload').classList.add('border-danger');
        showToast('请上传版本描述文件', 'error');
        return false;
      }
      
      return true;
    }
    
    // 初始化文件上传功能
    function initFileUploads() {
      // 版本描述文件上传
      const descFileUpload = document.getElementById('descFileUpload');
      const versionDescFile = document.getElementById('versionDescFile');
      const descFilePreview = document.getElementById('descFilePreview');
      const descFileName = document.getElementById('descFileName');
      const removeDescFile = document.getElementById('removeDescFile');
      
      descFileUpload.addEventListener('click', function() {
        versionDescFile.click();
      });
      
      versionDescFile.addEventListener('change', function(e) {
        if (e.target.files.length > 0) {
          const file = e.target.files[0];
          descFileName.textContent = file.name;
          descFilePreview.classList.remove('hidden');
          descFileUpload.classList.remove('border-danger');
        }
      });
      
      removeDescFile.addEventListener('click', function(e) {
        e.preventDefault();
        versionDescFile.value = '';
        descFilePreview.classList.add('hidden');
      });
      
      // 模块文件上传
      document.querySelectorAll('.file-upload-area').forEach(area => {
        const fileInput = area.querySelector('.module-file-upload');
        const previewArea = area.querySelector('.file-preview');
        
        area.addEventListener('click', function() {
          fileInput.click();
        });
        
        fileInput.addEventListener('change', function(e) {
          if (e.target.files.length > 0) {
            previewArea.innerHTML = '';
            previewArea.classList.remove('hidden');
            
            Array.from(e.target.files).forEach(file => {
              const fileEl = document.createElement('div');
              fileEl.className = 'flex items-center justify-between bg-gray-light p-2 rounded mb-1';
              fileEl.innerHTML = `
                <div class="flex items-center space-x-2">
                  <i class="fa fa-file-archive-o text-primary"></i>
                  <span class="text-sm truncate max-w-xs">${file.name}</span>
                </div>
                <button type="button" class="text-danger hover:text-danger/80 text-xs remove-file">
                  <i class="fa fa-times"></i>
                </button>
              `;
              previewArea.appendChild(fileEl);
            });
            
            // 更新状态
            area.closest('.module-upload-item').querySelector('.file-status')
              .className = 'text-xs px-2 py-1 bg-success/20 text-success rounded-full file-status';
              
            // 检查是否可以进入下一步
            checkStep3Completion();
          }
        });
        
        // 移除文件
        previewArea.addEventListener('click', function(e) {
          if (e.target.closest('.remove-file')) {
            e.target.closest('.file-preview div').remove();
            if (previewArea.children.length === 0) {
              previewArea.classList.add('hidden');
              area.closest('.module-upload-item').querySelector('.file-status')
                .className = 'text-xs px-2 py-1 bg-gray-light rounded-full file-status';
                
              // 检查是否可以进入下一步
              checkStep3Completion();
            }
          }
        });
      });
      
      // 自定义脚本文件上传
      document.querySelectorAll('.custom-script-file').forEach(fileInput => {
        const area = fileInput.closest('.custom-script-upload');
        const previewArea = area.querySelector('.script-preview');
        
        area.addEventListener('click', function() {
          fileInput.click();
        });
        
        fileInput.addEventListener('change', function(e) {
          if (e.target.files.length > 0) {
            previewArea.innerHTML = '';
            previewArea.classList.remove('hidden');
            
            Array.from(e.target.files).forEach(file => {
              const fileEl = document.createElement('div');
              fileEl.className = 'flex items-center justify-between bg-gray-light p-2 rounded mb-1';
              fileEl.innerHTML = `
                <div class="flex items-center space-x-2">
                  <i class="fa fa-file-code-o text-primary"></i>
                  <span class="text-sm truncate max-w-xs">${file.name}</span>
                </div>
                <button type="button" class="text-danger hover:text-danger/80 text-xs remove-script">
                  <i class="fa fa-times"></i>
                </button>
              `;
              previewArea.appendChild(fileEl);
            });
            
            // 检查脚本完整性
            checkScriptIntegrityForModule(area.closest('.module-upload-item'));
            
            // 检查是否可以进入下一步
            checkStep3Completion();
          }
        });
        
        // 移除脚本文件
        previewArea.addEventListener('click', function(e) {
          if (e.target.closest('.remove-script')) {
            e.target.closest('.script-preview div').remove();
            if (previewArea.children.length === 0) {
              previewArea.classList.add('hidden');
              
              // 检查脚本完整性
              checkScriptIntegrityForModule(area.closest('.module-upload-item'));
              
              // 检查是否可以进入下一步
              checkStep3Completion();
            }
          }
        });
      });
    }
    
    // 初始化拓扑选择功能
    function initTopologySelection() {
      // 查看模块按钮
      document.querySelectorAll('.view-modules-btn').forEach(btn => {
        btn.addEventListener('click', function(e) {
          e.preventDefault();
          const targetId = this.getAttribute('data-target');
          const targetEl = document.getElementById(targetId);
          
          if (targetEl.classList.contains('hidden')) {
            targetEl.classList.remove('hidden');
            this.innerHTML = '收起模块 <i class="fa fa-chevron-up text-xs"></i>';
          } else {
            targetEl.classList.add('hidden');
            this.innerHTML = '查看模块 <i class="fa fa-chevron-down text-xs"></i>';
          }
        });
      });
      
      // 拓扑选择
      const topologyRadios = document.querySelectorAll('.topology-radio');
      const selectedToposEl = document.getElementById('selectedTopos');
      const toStep3Btn = document.getElementById('toStep3Btn');
      
      topologyRadios.forEach(radio => {
        radio.addEventListener('change', function() {
          if (this.checked) {
            const topologyItem = this.closest('.topology-item');
            const neid = topologyItem.getAttribute('data-neid');
            const nename = topologyItem.getAttribute('data-nename');
            
            selectedToposEl.innerHTML = `
              <div class="bg-white border border-gray-200 rounded px-3 py-1.5 flex items-center space-x-2">
                <span class="text-sm">${neid} - ${nename}</span>
                <button type="button" class="text-gray-400 hover:text-danger remove-topo">
                  <i class="fa fa-times-circle"></i>
                </button>
              </div>
            `;
            
            toStep3Btn.removeAttribute('disabled');
          }
        });
      });
      
      // 移除选中的拓扑
      selectedToposEl.addEventListener('click', function(e) {
        if (e.target.closest('.remove-topo')) {
          topologyRadios.forEach(radio => {
            radio.checked = false;
          });
          selectedToposEl.innerHTML = '<p class="text-gray-dark text-sm italic">未选择任何拓扑</p>';
          toStep3Btn.setAttribute('disabled', 'disabled');
        }
      });
    }
    
    // 初始化脚本选择功能
    function initScriptSelection() {
      // 脚本选择变化
      document.querySelectorAll('.module-script-select').forEach(select => {
        select.addEventListener('change', function() {
          const customUploadArea = this.parentElement.nextElementSibling;
          const moduleItem = this.closest('.module-upload-item');
          const scriptCheckResult = this.closest('.module-upload-item').querySelector('.script-check-result');
          
          if (this.value === 'custom') {
            customUploadArea.classList.remove('hidden');
            // 清空脚本检查结果
            if (scriptCheckResult) {
              scriptCheckResult.classList.add('hidden');
            }
          } else if (this.value) {
            customUploadArea.classList.add('hidden');
            // 检查脚本完整性
            checkScriptIntegrityForModule(moduleItem);
          } else {
            customUploadArea.classList.add('hidden');
            // 清空脚本检查结果
            if (scriptCheckResult) {
              scriptCheckResult.classList.add('hidden');
            }
          }
          
          // 检查是否可以进入下一步
          checkStep3Completion();
        });
      });
      
      // 新脚本包上传区域点击事件
      document.getElementById('newScriptPackage').parentElement.addEventListener('click', function() {
        document.getElementById('newScriptPackage').click();
      });
      
      // 新脚本包上传处理
      document.getElementById('newScriptPackage').addEventListener('change', function(e) {
        if (e.target.files.length > 0) {
          const fileName = e.target.files[0].name;
          // 这里可以添加实际的上传逻辑
          showToast(`脚本包 ${fileName} 上传成功`, 'success');
          
          // 添加到脚本包列表
          const scriptList = document.querySelector('#scriptManagerModal .space-y-2');
          const newScriptEl = document.createElement('div');
          newScriptEl.className = 'border border-gray-200 rounded-lg p-3 flex justify-between items-center';
          newScriptEl.innerHTML = `
            <div>
              <p class="font-medium">${fileName}</p>
              <p class="text-xs text-gray-dark">新上传的脚本包</p>
            </div>
            <button class="text-primary text-sm" onclick="selectScriptPackage('${fileName}')">选择</button>
          `;
          scriptList.prepend(newScriptEl);
          
          // 添加到选择下拉框
          document.querySelectorAll('.module-script-select').forEach(select => {
            const option = document.createElement('option');
            option.value = fileName;
            option.textContent = fileName;
            select.insertBefore(option, select.lastElementChild);
          });
        }
      });
    }
    
    // 打开脚本管理工具
    function openScriptManager() {
      openModal('scriptManagerModal');
    }
    
    // 选择脚本包
    function selectScriptPackage(packageName) {
      currentScriptPackage = packageName;
      
      // 在当前活动的模块中选择脚本包
      const activeModule = document.querySelector('.module-upload-item:focus-within') || 
                          document.querySelector('.module-upload-item:first-child');
                          
      if (activeModule) {
        const select = activeModule.querySelector('.module-script-select');
        select.value = packageName;
        
        // 触发change事件
        const event = new Event('change');
        select.dispatchEvent(event);
      }
      
      closeModal('scriptManagerModal');
      showToast(`已选择脚本包: ${packageName}`, 'success');
    }
    
    // 检查模块的脚本完整性
    function checkScriptIntegrityForModule(moduleItem) {
      const scriptSelect = moduleItem.querySelector('.module-script-select');
      const scriptCheckResult = moduleItem.querySelector('.script-check-result');
      const resultContainer = moduleItem.querySelector('.script-check-result > div');
      
      // 模拟脚本检查结果
      let scriptChecks = [];
      
      if (scriptSelect.value === 'script-package-1.0.0.zip') {
        // 完整的脚本包
        scriptChecks = REQUIRED_SCRIPTS.map(script => ({
          ...script,
          exists: true
        }));
      } else if (scriptSelect.value === 'script-package-1.1.0.zip') {
        // 完整的脚本包
        scriptChecks = REQUIRED_SCRIPTS.map(script => ({
          ...script,
          exists: true
        }));
      } else if (scriptSelect.value === 'custom' && 
                moduleItem.querySelector('.script-preview:not(.hidden)')) {
        // 自定义脚本包，模拟大部分存在，少部分缺失
        scriptChecks = REQUIRED_SCRIPTS.map((script, index) => ({
          ...script,
          exists: index !== 2 // 模拟第三个脚本缺失
        }));
      } else {
        // 没有选择脚本包或没有上传自定义脚本
        scriptCheckResult.classList.add('hidden');
        return false;
      }
      
      // 显示检查结果
      resultContainer.innerHTML = '';
      scriptChecks.forEach(script => {
        const span = document.createElement('span');
        span.className = script.exists ? 'script-required' : 'script-missing';
        span.textContent = script.name;
        resultContainer.appendChild(span);
      });
      
      scriptCheckResult.classList.remove('hidden');
      
      // 返回是否所有脚本都存在
      return scriptChecks.every(script => script.exists);
    }
    
    // 验证所有脚本的完整性
    function validateScriptIntegrity() {
      let allValid = true;
      const scriptIntegrityCheck = document.getElementById('scriptIntegrityCheck');
      
      document.querySelectorAll('.module-upload-item').forEach(moduleItem => {
        const isValid = checkScriptIntegrityForModule(moduleItem);
        if (!isValid) {
          allValid = false;
        }
      });
      
      // 更新步骤4的脚本检查结果显示
      if (allValid) {
        scriptIntegrityCheck.className = 'mb-6 p-3 rounded-lg border border-success/30 bg-success/10';
        scriptIntegrityCheck.innerHTML = `
          <div class="flex items-center">
            <i class="fa fa-check-circle text-success mr-2"></i>
            <h3 class="font-medium">脚本完整性检查通过</h3>
          </div>
          <p class="text-sm text-gray-dark mt-1">所有必需的脚本文件均已包含且无重复</p>
        `;
      } else {
        scriptIntegrityCheck.className = 'mb-6 p-3 rounded-lg border border-danger/30 bg-danger/10';
        scriptIntegrityCheck.innerHTML = `
          <div class="flex items-center">
            <i class="fa fa-exclamation-circle text-danger mr-2"></i>
            <h3 class="font-medium">脚本完整性检查失败</h3>
          </div>
          <p class="text-sm text-gray-dark mt-1">部分模块缺少必需的脚本文件，请检查并补充</p>
        `;
      }
      
      if (!allValid) {
        showToast('脚本文件不完整，请检查并补充缺少的脚本', 'error');
        goToStep(3);
      }
      
      return allValid;
    }
    
    // 检查步骤3是否完成，以启用下一步按钮
    function checkStep3Completion() {
      let allModulesComplete = true;
      
      document.querySelectorAll('.module-upload-item').forEach(moduleItem => {
        // 检查是否选择了脚本包或上传了自定义脚本
        const scriptSelect = moduleItem.querySelector('.module-script-select');
        const customScriptUploaded = moduleItem.querySelector('.custom-script-upload .script-preview:not(.hidden)');
        const scriptValid = checkScriptIntegrityForModule(moduleItem);
        
        // 检查是否上传了其他升级文件
        const filesUploaded = moduleItem.querySelector('.file-preview:not(.hidden)');
        
        // 检查该模块是否完成
        const moduleComplete = (scriptSelect.value && scriptValid) && filesUploaded;
        
        if (!moduleComplete) {
          allModulesComplete = false;
        }
      });
      
      // 更新下一步按钮状态
      const toStep4Btn = document.getElementById('toStep4Btn');
      if (allModulesComplete) {
        toStep4Btn.removeAttribute('disabled');
      } else {
        toStep4Btn.setAttribute('disabled', 'disabled');
      }
    }
    
    // 初始化打包功能
    function initPackaging() {
      // 开始打包按钮
      document.getElementById('startPackagingBtn').addEventListener('click', function() {
        const packagingProgress = document.getElementById('packagingProgress');
        const packagingComplete = document.getElementById('packagingComplete');
        const progressBar = document.getElementById('progressBar');
        const progressPercent = document.getElementById('progressPercent');
        const progressMessage = document.getElementById('progressMessage');
        const finalPackageName = document.getElementById('finalPackageName');
        
        // 显示进度条
        packagingProgress.classList.remove('hidden');
        packagingComplete.classList.add('hidden');
        this.setAttribute('disabled', 'disabled');
        
        // 模拟打包进度
        let progress = 0;
        const packageName = document.getElementById('packageName').value.trim() || 'upgrade-package';
        const packageFormat = document.getElementById('packageFormat').value;
        finalPackageName.textContent = `${packageName}.${packageFormat}`;
        
        const interval = setInterval(() => {
          progress += Math.random() * 10;
          if (progress >= 100) {
            progress = 100;
            clearInterval(interval);
            
            // 模拟打包完成
            setTimeout(() => {
              packagingProgress.classList.add('hidden');
              packagingComplete.classList.remove('hidden');
              this.removeAttribute('disabled');
              showToast('升级包打包完成', 'success');
            }, 500);
          }
          
          // 更新进度
          progressBar.style.width = `${progress}%`;
          progressPercent.textContent = `${Math.round(progress)}%`;
          
          // 更新进度消息
          if (progress < 30) {
            progressMessage.textContent = '正在收集文件...';
          } else if (progress < 60) {
            progressMessage.textContent = '正在压缩文件...';
          } else if (progress < 90) {
            progressMessage.textContent = '正在生成校验信息...';
          } else {
            progressMessage.textContent = '准备完成...';
          }
        }, 300);
      });
      
      // 下载按钮
      document.getElementById('downloadPackageBtn').addEventListener('click', function() {
        showToast('文件开始下载', 'success');
      });
      
      // 打包格式变更
      document.getElementById('packageFormat').addEventListener('change', function() {
        updateSummaryInfo();
      });
    }
    
    // 更新摘要信息
    function updateSummaryInfo() {
      document.getElementById('summaryPackageName').textContent = 
        document.getElementById('packageName').value.trim() || '-';
      
      document.getElementById('summaryDescFile').textContent = 
        document.getElementById('descFileName').textContent || '-';
      
      const selectedTopo = document.getElementById('selectedTopos').querySelector('span')?.textContent || '-';
      document.getElementById('summaryTopologies').textContent = selectedTopo;
      
      const moduleCount = document.querySelectorAll('.module-upload-item').length;
      document.getElementById('summaryModuleCount').textContent = moduleCount;
      
      const packageFormat = document.getElementById('packageFormat').options[
        document.getElementById('packageFormat').selectedIndex
      ].text;
      document.getElementById('summaryPackageFormat').textContent = packageFormat;
    }
    
    // 打开模态框
    function openModal(modalId) {
      document.getElementById(modalId).classList.remove('hidden');
      document.body.style.overflow = 'hidden';
    }
    
    // 关闭模态框
    function closeModal(modalId) {
      document.getElementById(modalId).classList.add('hidden');
      document.body.style.overflow = '';
    }
    
    // 显示提示消息
    function showToast(message, type = 'info') {
      const toast = document.getElementById('toast');
      let icon = 'fa-info-circle';
      let bgColor = 'bg-primary';
      
      if (type === 'success') {
        icon = 'fa-check-circle';
        bgColor = 'bg-success';
      } else if (type === 'error') {
        icon = 'fa-times-circle';
        bgColor = 'bg-danger';
      } else if (type === 'warning') {
        icon = 'fa-exclamation-circle';
        bgColor = 'bg-warning';
      }
      
      toast.className = `fixed top-4 right-4 px-4 py-3 rounded-lg shadow-lg transform transition-transform duration-300 flex items-center space-x-2 z-50 ${bgColor} text-white`;
      toast.innerHTML = `
        <i class="fa ${icon}"></i>
        <span>${message}</span>
      `;
      
      // 显示提示
      setTimeout(() => {
        toast.style.transform = 'translateX(0)';
      }, 100);
      
      // 3秒后隐藏
      setTimeout(() => {
        toast.style.transform = 'translateX(calc(100% + 20px))';
      }, 3000);
    }
  </script>
</body>
</html>
